package com.example.docmanagement.entity;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;
import java.util.UUID;

/**
 * 文件元数据实体类
 * 对应数据库表：file_metadata
 * 
 * 用途：存储所有上传到 MinIO 的文件元信息
 * 包括：文档图片、附件、Markdown 文件、用户头像、文档封面等
 */
@Entity
@Table(name = "file_metadata")
@EntityListeners(AuditingEntityListener.class)
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class FileMetadata {

    /**
     * 文件 ID（主键，自增）
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    // ============================================================================
    // 文件基本信息
    // ============================================================================

    /**
     * 原始文件名
     * 示例：spring-boot-guide.pdf
     */
    @Column(name = "file_name", nullable = false)
    private String fileName;

    /**
     * MinIO 完整路径（全局唯一）
     * 格式：bucket/year/month/uuid.ext
     * 示例：doc-images/2024/11/a1b2c3d4-e5f6-7890-abcd-ef1234567890.jpg
     */
    @Column(name = "file_path", nullable = false, unique = true, length = 500)
    private String filePath;

    /**
     * 所属 Bucket 名称
     * 示例：doc-images, doc-contents, doc-attachments
     */
    @Column(name = "bucket_name", nullable = false, length = 100)
    private String bucketName;

    /**
     * MinIO Object Key（不含 Bucket）
     * 格式：year/month/uuid.ext
     * 示例：2024/11/a1b2c3d4-e5f6-7890-abcd-ef1234567890.jpg
     */
    @Column(name = "object_key", nullable = false, length = 400)
    private String objectKey;

    /**
     * 文件大小（字节）
     */
    @Column(name = "file_size", nullable = false)
    private Long fileSize;

    /**
     * MIME 类型
     * 示例：image/jpeg, application/pdf, text/markdown
     */
    @Column(name = "mime_type", nullable = false, length = 100)
    private String mimeType;

    /**
     * 文件扩展名
     * 示例：.jpg, .pdf, .md
     */
    @Column(name = "file_extension", length = 20)
    private String fileExtension;

    // ============================================================================
    // 文件分类
    // ============================================================================

    /**
     * 文件类型（枚举）
     * 可选值：image, document, markdown, avatar, cover, other
     */
    @Column(name = "file_type", nullable = false, length = 20)
    private String fileType;

    /**
     * 文件分类（业务分类）
     * 示例：doc-image, doc-attachment, user-avatar, doc-cover
     */
    @Column(name = "file_category", length = 50)
    private String fileCategory;

    // ============================================================================
    // 文件标识（用于去重和校验）
    // ============================================================================

    /**
     * MD5 哈希值（用于文件去重）
     */
    @Column(name = "md5_hash", length = 32)
    private String md5Hash;

    /**
     * SHA256 哈希值（可选，更安全）
     */
    @Column(name = "sha256_hash", length = 64)
    private String sha256Hash;

    // ============================================================================
    // 图片特有字段
    // ============================================================================

    /**
     * 图片宽度（像素）
     */
    @Column(name = "width")
    private Integer width;

    /**
     * 图片高度（像素）
     */
    @Column(name = "height")
    private Integer height;

    /**
     * 是否有缩略图
     */
    @Column(name = "has_thumbnail")
    private Boolean hasThumbnail = false;

    /**
     * 缩略图路径
     * 示例：thumbnails/2024/11/xxx_thumb.jpg
     */
    @Column(name = "thumbnail_path", length = 500)
    private String thumbnailPath;

    /**
     * 缩略图访问 URL
     */
    @Column(name = "thumbnail_url", columnDefinition = "TEXT")
    private String thumbnailUrl;

    // ============================================================================
    // 访问控制
    // ============================================================================

    /**
     * 访问策略
     * 可选值：public, private, authenticated
     */
    @Column(name = "access_policy", length = 20)
    private String accessPolicy = "public";

    /**
     * 是否公开（冗余字段，方便查询）
     */
    @Column(name = "is_public")
    private Boolean isPublic = true;

    // ============================================================================
    // 使用统计
    // ============================================================================

    /**
     * 下载次数
     */
    @Column(name = "download_count")
    private Integer downloadCount = 0;

    /**
     * 查看次数（主要用于图片）
     */
    @Column(name = "view_count")
    private Integer viewCount = 0;

    // ============================================================================
    // 关联信息
    // ============================================================================

    /**
     * 关联的文档 ID（可为空）
     * 未关联的文件：临时上传、待关联
     */
    @Column(name = "document_id")
    private Long documentId;

    /**
     * 上传者用户 ID
     */
    @Column(name = "uploaded_by")
    private UUID uploadedBy;

    // ============================================================================
    // 导入相关
    // ============================================================================

    /**
     * 原始来源 URL（从外部 URL 下载时记录）
     */
    @Column(name = "source_url", columnDefinition = "TEXT")
    private String sourceUrl;

    /**
     * 是否从 URL 导入
     */
    @Column(name = "imported_from_url")
    private Boolean importedFromUrl = false;

    /**
     * 上传来源
     * 可选值：editor（Monaco 编辑器）、attachment（文档附件上传）、manual（手动上传）
     * 用于区分文件的上传来源，决定是否允许删除（editor 来源的文件不应删除，因为会影响 Markdown 内容）
     */
    @Column(name = "upload_source", length = 20)
    private String uploadSource = "attachment";

    // ============================================================================
    // 元数据（JSONB 格式）
    // ============================================================================

    /**
     * 额外元数据（JSONB 格式）
     * 可存储：EXIF 信息、自定义标签、备注等
     * 
     * 示例：
     * {
     *   "exif": {"camera": "Canon EOS", "date": "2024-11-03"},
     *   "tags": ["screenshot", "architecture"],
     *   "description": "系统架构图"
     * }
     * 
     * 注意：PostgreSQL JSONB 类型，在 Java 中映射为 String
     */
    @Column(name = "metadata", columnDefinition = "jsonb")
    @JdbcTypeCode(SqlTypes.JSON)
    private String metadata = "{}";

    // ============================================================================
    // 软删除
    // ============================================================================

    /**
     * 软删除时间
     */
    @Column(name = "deleted_at")
    private LocalDateTime deletedAt;

    /**
     * 删除者 ID
     */
    @Column(name = "deleted_by")
    private UUID deletedBy;

    // ============================================================================
    // 时间戳（自动管理）
    // ============================================================================

    /**
     * 创建时间（自动填充）
     */
    @CreatedDate
    @Column(name = "created_at", nullable = false, updatable = false)
    private LocalDateTime createdAt;

    /**
     * 更新时间（自动填充）
     */
    @LastModifiedDate
    @Column(name = "updated_at", nullable = false)
    private LocalDateTime updatedAt;

    // ============================================================================
    // JPA 回调方法
    // ============================================================================

    /**
     * 持久化之前的回调
     */
    @PrePersist
    public void prePersist() {
        if (this.createdAt == null) {
            this.createdAt = LocalDateTime.now();
        }
        if (this.updatedAt == null) {
            this.updatedAt = LocalDateTime.now();
        }
        // 根据 accessPolicy 设置 isPublic
        if (this.accessPolicy != null) {
            this.isPublic = "public".equals(this.accessPolicy);
        }
    }

    /**
     * 更新之前的回调
     */
    @PreUpdate
    public void preUpdate() {
        this.updatedAt = LocalDateTime.now();
    }

    // ============================================================================
    // 工具方法
    // ============================================================================

    /**
     * 获取完整的文件访问 URL
     * 
     * @param minioEndpoint MinIO 服务器地址
     * @return 完整 URL
     */
    public String getFileUrl(String minioEndpoint) {
        return minioEndpoint + "/" + this.filePath;
    }

    /**
     * 是否为图片类型
     */
    public boolean isImage() {
        return "image".equals(this.fileType);
    }

    /**
     * 是否为文档类型
     */
    public boolean isDocument() {
        return "document".equals(this.fileType);
    }

    /**
     * 是否为 Markdown 文件
     */
    public boolean isMarkdown() {
        return "markdown".equals(this.fileType);
    }

    /**
     * 是否已软删除
     */
    public boolean isDeleted() {
        return this.deletedAt != null;
    }
}

